package log

import (
    "bytes"
    "context"
    "encoding/json"
    "errors"
    "fmt"
    "time"

    elastic "github.com/elastic/go-elasticsearch/v6"
    "github.com/elastic/go-elasticsearch/v6/esapi"
    "git.inspur.com/x/common/loggerfactory"
)

var logger = loggerfactory.GetLogger()

func QueryEs(client *elastic.Client, requestId string) (string, error) {
    var buf bytes.Buffer
    query := map[string]interface{}{
        "query": map[string]interface{}{
            "match": map[string]interface{}{
                "requestId": requestId,
            },
        },
        "sort": map[string]interface{}{
            "long_time": map[string]interface{}{
                "order": "asc",
            },
        },
    }
    if err := json.NewEncoder(&buf).Encode(query); err != nil {
        _ = logger.Error("QueryEs: Error encoding query, %v", err)
        return "", err
    }

    size := 1000
    res, err := client.Search(
        client.Search.WithContext(context.Background()),
        client.Search.WithIndex("fcs-*"),
        client.Search.WithBody(&buf),
        client.Search.WithTrackTotalHits(true),
        client.Search.WithPretty(),
        client.Search.WithScroll(10*time.Second),
        client.Search.WithSize(size),
    )
    if err != nil {
        _ = logger.Error("QueryEs: Error getting response, %v", err)
        return "", err
    }

    resResult, err := getResResult(res)
    if err != nil {
        _ = logger.Error("QueryEs: Error getting res result, %v", err)
        return "", err
    }

    var log bytes.Buffer
    for _, hit := range resResult["hits"].(map[string]interface{})["hits"].([]interface{}) {
        log.WriteString(hit.(map[string]interface{})["_source"].(map[string]interface{})["log"].(string))
    }
    // 没有scroll id的时候直接返回
    if resResult["_scroll_id"] == nil {
        return log.String(), nil
    }
    scrollId := resResult["_scroll_id"].(string)
    for {
        res, err := client.Scroll(
            client.Scroll.WithScrollID(scrollId),
            client.Scroll.WithScroll(10*time.Second),
        )
        if err != nil {
            _ = logger.Error("QueryEs: Error getting scroll response, %v", err)
            break
        }
        resResult, err := getResResult(res)
        if err != nil {
            _ = logger.Error("QueryEs: Error getting scroll res result, %v", err)
            break
        }
        if len(resResult["hits"].(map[string]interface{})["hits"].([]interface{})) == 0 {
            break
        }
        for _, hit := range resResult["hits"].(map[string]interface{})["hits"].([]interface{}) {
            log.WriteString(hit.(map[string]interface{})["_source"].(map[string]interface{})["log"].(string))
        }
    }

    return log.String(), nil
}

func getResResult(res *esapi.Response) (map[string]interface{}, error) {
    defer res.Body.Close()
    if res.IsError() {
        var e map[string]interface{}
        if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
            _ = logger.Error("getLogFromRes: Error parsing the response body, %v", err)
            return nil, err
        } else {
            return nil, errors.New(fmt.Sprintf("get res error %s", e))
        }
    }

    var r map[string]interface{}
    if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
        _ = logger.Error("getLogFromRes: Error parsing the response body, %v", err)
        return nil, err
    }

    return r, nil
}
